<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>前置知识</title>
</head>
<body>
    <div id="test">
        测试
    </div>
    <ul id="fragment">
        <li>第一个</li>
        <li>第二个</li>
        <li>第三个</li>
    </ul>
</body>
<script>
    console.log("--------------------------伪数组转真数组-----------------------")
    // 1.[].slice.call():将伪数组转换为真数组
    const lis=document.getElementsByTagName('li')
    console.log(lis)
    //判断是否为真数组
    console.log(lis instanceof Array,lis[1].innerHTML,lis.forEach) //false "第二个" undefined
    const lis2=Array.prototype.slice.call(lis)
    console.log(lis2 instanceof Array,lis2[1].innerHTML,lis2.forEach) //true "第二个" f forEach()

    // 2.node.nodeType:用来得到节点类型,用来区分不同类型的节点，比如 元素, 文本 和 注释。
    const elementNode=document.getElementById("test")
    // 获取id
    const attrNode=elementNode.getAttributeNode("id")
    // 获取内容
    const textNode=elementNode.firstChild
    console.log(elementNode,attrNode,textNode)
    console.log(elementNode.nodeType,attrNode.nodeType,textNode.nodeType)

    console.log("--------------------------Object.defineProperty-----------------------")    
    // 3.Object.defineProperty(obj, prop, descriptor)
    const obj={
        firstName:'A',
        lastName:'B'
    }
    //给obj添加fullName
    /**
    属性描述符:
    1.数据描述符
        configurable:是否可以重新定义
        enumerable:是否可以枚举
        value:初始值
        writable:是否可以修改属性值
    2.访问描述符
        get:回调函数,根据其他的属性动态计算得到当前属性值
        set:回调函数,监事当前属性值的变化,更新其他相关属性值
    */
    Object.defineProperty(obj,'fullName',{
        get(){
            return this.firstName+'-'+this.lastName
        },
        set(value){
            // split() 方法使用指定的分隔符字符串将一个String对象分割成字符串数组，以将字符串分隔为子字符串，以确定每个拆分的位置
            const names=value.split('-')
            this.firstName=names[0]
            this.lastName=names[1]
        }
    })
    console.log(obj.fullName)
    obj.firstName="wzj"
    obj.lastName="hh"
    console.log(obj.fullName)
    obj.fullName="E-F"
    console.log(obj.firstName,obj.lastName)

    Object.defineProperty(obj,'fullName2',{
        configurable:false,
        enumerable:true,
        value:'初始值',
        writable:false
    })
    console.log("配置参数")
    console.log(obj.fullName2)
    obj.fullName2="hh"
    console.log(obj.fullName2)
    // 验证是否能重新定义
    // Object.defineProperty(obj,'fullName2',{
    //     configurable:false,
    //     enumerable:false,
    //     value:'初始值',
    //     writable:true
    // })
    console.log("--------------------------Object.keys-----------------------")
    // 4.Object.keys(obj)
    const names=Object.keys(obj)
    console.log(names)
    console.log("--------------------------hasOwnProperty-----------------------")
    // 5.obj.hasOwnProperty(prop)
    console.log(obj.hasOwnProperty("fullName"),obj.hasOwnProperty('toString'))
    console.log("--------------------------documentFragment-----------------------")
    // 6.DocumentFragment:文档碎片
    // document:对应显示的页面,包含n个element,一旦更新document内部的某个元素界面更新
    // documentFragment:内存中保存n个element的容器对象(不与界面关联),如果更新framgnet中的某个元素,界面不变
    const ul=document.getElementById("fragment")
    // 创建fragment
    const fragment=document.createDocumentFragment()
    console.log(fragment)
    // 取出ul中所有子节点取出保存到fragment
    let child
    // 一个节点只能有一个父亲
    while (child=ul.firstChild) {
        fragment.appendChild(child) //先将child从ul中移除,添加为fragment子节点
    }
    // 更新fragment中li文本
    console.log(fragment.childNodes)
    Array.prototype.slice.call(fragment.childNodes).forEach(node=>{
        if(node.nodeType===1){//元素节点
            console.log(node.textContent)
            node.textContent="hh"
        }
    })
    // 将fragment插入ul
    ul.appendChild(fragment)

</script>
</html>